#include "display_driver.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"


#define TFT_WIDTH 250
#define TFT_HIGH 122
#define BLOCK 11 // 122/12=10.17

#define BYTE_BIT_SIZE 8
#define GPIO_OUTPUT_PIN_SEL                                                    \
  (1ULL << 26) | (1ULL << 25) | (1ULL << 33) | (1ULL << 32) | (1ULL << 9)

// 每个块是2*12大小，
uint8_t screen_map[125 * BLOCK * 3] = {0};

void tft_fill_rect();

void tft_spi_write(uint8_t data) {
  set_pin_low(TFT_CS);
  for (int i = 0; i < 8; i++) {
    if (data & 0x80) {
      set_pin_high(TFT_SDA);
    } else {
      set_pin_low(TFT_SDA);
    }
    data <<= 1;
    set_pin_low(TFT_SCK);
    set_pin_high(TFT_SCK);
  }
  set_pin_high(TFT_CS);
}

void tft_send_cmd(uint8_t cmd) {
  set_pin_low(TFT_DC);
  tft_spi_write(cmd);
}

void tft_send_data(uint8_t data) {
  set_pin_high(TFT_DC);
  tft_spi_write(data);
}

void st7305_init() {
  tft_pin_init();
  set_pin_high(TFT_RST);
  vTaskDelay(pdMS_TO_TICKS(10));
  set_pin_low(TFT_RST);
  vTaskDelay(pdMS_TO_TICKS(10));
  set_pin_high(TFT_RST);
  vTaskDelay(pdMS_TO_TICKS(120));

  set_pin_high(TFT_DC);
  set_pin_high(TFT_CS);

  tft_send_cmd(0xD6); // NVM Load Control
  tft_send_data(0x17);
  tft_send_data(0X02);

  tft_send_cmd(0xD1); // Booster Enable
  tft_send_data(0X01);

  tft_send_cmd(0xC0);  // Gate Voltage Setting
  tft_send_data(0X0E); // VGH=15V
  tft_send_data(0X05); // VGL=-7.5V

  tft_send_cmd(0xC1);  // VSHP Setting
  tft_send_data(0X41); // VSHP1=5V
  tft_send_data(0X41); // VSHP2=5V
  tft_send_data(0X41); // VSHP3=5V
  tft_send_data(0X41); // VSHP4=5V

  tft_send_cmd(0xC2);  // VSLP Setting
  tft_send_data(0X32); // VSLP1=1V
  tft_send_data(0X32); // VSLP2=1V
  tft_send_data(0X32); // VSLP3=1V
  tft_send_data(0X32); // VSLP4=1V

  tft_send_cmd(0xC4);  // VSHN Setting
  tft_send_data(0X4B); // VSHN1=-4V
  tft_send_data(0X4B); // VSHN2=-4V
  tft_send_data(0X4B); // VSHN3=-4V
  tft_send_data(0X4B); // VSHN4=-4V

  tft_send_cmd(0xC5);  // VSLN Setting
  tft_send_data(0X00); // VSLN1=1V
  tft_send_data(0X00); // VSLN2=1V
  tft_send_data(0X00); // VSLN3=1V
  tft_send_data(0X00); // VSLN4=1V

  tft_send_cmd(0xD8); // HPM=32Hz
  tft_send_data(0XA6);
  tft_send_data(0XE9);

  tft_send_cmd(0xB2);  // Frame Rate Control
  tft_send_data(0X11); // HPM=32hz ; LPM=0.5hz

  tft_send_cmd(0xB3);  // Update Period Gate EQ Control in HPM
  tft_send_data(0XE5); //
  tft_send_data(0XF6); //
  tft_send_data(0X05); // HPM EQ Control
  tft_send_data(0X46); //
  tft_send_data(0X77); //
  tft_send_data(0X77); //
  tft_send_data(0X77); //
  tft_send_data(0X77); //
  tft_send_data(0X76); //
  tft_send_data(0X45); //

  tft_send_cmd(0xB4);  // Update Period Gate EQ Control in LPM
  tft_send_data(0X05); // LPM EQ Control
  tft_send_data(0X46); //
  tft_send_data(0X77); //
  tft_send_data(0X77); //
  tft_send_data(0X77); //
  tft_send_data(0X77); //
  tft_send_data(0X76); //
  tft_send_data(0X45); //

  tft_send_cmd(0xB7);  // Source EQ Enable
  tft_send_data(0X13); //

  tft_send_cmd(0xB0);  // Gate Line Setting
  tft_send_data(0X3F); // 252 line

  tft_send_cmd(0x11); // Sleep out
  vTaskDelay(pdMS_TO_TICKS(120));

  tft_send_cmd(0xC9);  // Source Voltage Select
  tft_send_data(0x00); // VSHP1; VSLP1 ; VSHN1 ; VSLN1

  tft_send_cmd(0xC7); // ultra low power code
  tft_send_data(0xC1);
  tft_send_data(0x41);
  tft_send_data(0x26);

  tft_send_cmd(0x36);  // Memory Data Access Control
  tft_send_data(0X00); // MX=0 ; DO=0

  tft_send_cmd(0x3A);  // Data Format Select
  tft_send_data(0X11); // 10:4write for 24bit ; 11: 3write for 24bit

  tft_send_cmd(0xB9);  // Gamma Mode Setting
  tft_send_data(0X20); // 20: Mono 00:4GS

  tft_send_cmd(0xB8);  // Panel Setting
  tft_send_data(0X25); // dot inversion; one line interval; dot inversion

  // tft_send_cmd(0x21); //Inverse

  // WRITE RAM 122x250
  tft_send_cmd(0x2A); // Column Address Setting
  tft_send_data(0X19);
  tft_send_data(0X23);

  tft_send_cmd(0x2B); // Row Address Setting
  tft_send_data(0X00);
  tft_send_data(0X7C);

  tft_send_cmd(0x35);  // TE
  tft_send_data(0X00); //

  tft_send_cmd(0xD0);  // Auto power down
  tft_send_data(0XFF); //

  tft_send_cmd(0x39); // 0x39 low power 0x38 high power
  tft_send_cmd(0x29); // DISPLAY ON
}

void set_windows_size() {
  // WRITE RAM 122x250
  tft_send_cmd(0x2A); // Column Address Setting
  tft_send_data(0X19);
  tft_send_data(0X23);

  tft_send_cmd(0x2B); // Row Address Setting
  tft_send_data(0X00);
  tft_send_data(0X7C);
}

void bitWrite(uint8_t *byte, uint8_t bit, bool value) {
  if (value) {
    *byte |= (1 << bit);
  } else {
    *byte &= ~(1 << bit);
  }
}

void setPixel(uint8_t x, uint8_t y, bool value) {
  x = TFT_WIDTH - x;
  y = TFT_HIGH - y;
  uint32_t bits_pos = (x / 2) * BLOCK * 3 + y / 4;
  uint32_t bit = 7 - ((y % 4) * 2 + (x % 2));
  bitWrite(&screen_map[bits_pos], bit, value);
}

void tft_fill_rect() {
  set_windows_size();
  tft_send_cmd(0x2C);
  for (int i = 0; i < sizeof(screen_map); i++) {
    tft_send_data(screen_map[i]);
  }
}
